package algebra;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.String;
import java.text.DecimalFormat;

import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CharStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.TokenStream;
import org.antlr.runtime.tree.CommonTreeNodeStream;

import algebra.BasicAlgebraEquParser.evaluator_return;

public class AlgebraEquationTest {
	
	public static void main(String[] args) throws RecognitionException, IOException{
		AlgebraEquationTest test = new AlgebraEquationTest();

		//test.recognitionTest();
		test.inputTest();
		//test.recognitionTest2();
	}
	
	public void recognitionTest() throws RecognitionException{
		System.out.println("<poly> + <poly> = d");
		probFromTemplate("(<poly> + <poly>) = d");
		System.out.println("\n<poly> + <poly> = <poly> - f");
		probFromTemplate("<poly> + <poly> = <poly> - f");
		System.out.println("\n<poly> + <poly> + a = d + g - <poly>");
		probFromTemplate("<poly> + <poly> + a = d + g - <poly>");
		System.out.println("\n<poly> + d = 3");
		probFromTemplate("<poly> + d = 3");
		/*System.out.println("\n<poly> - <poly> = d");
		probFromTemplate("<poly> - <poly> = d");
		/*System.out.println("\n<poly> + <poly2> = <poly> - e");
		probFromTemplate("<poly> + <poly2> = <poly> - e");*/
		System.out.println("\n<poly> * <poly> = d");
		probFromTemplate("<poly> * <poly> = d");
		/*System.out.println("\n<poly> / <poly> = d");
		probFromTemplate("<poly> / <poly> = d");*/
		System.out.println("x^2 - 81 = 0");
		probFromTemplate("(x^2) - 81 = 0");
		System.out.println("\nx^2 = 7*x");
		probFromTemplate("x^2 = 7*x");
		System.out.println("\nx^2 = 36");
		probFromTemplate("x^2 = 36");
		System.out.println("\nx^2 - 3*x - 10 = 0");
		probFromTemplate("x^2 - 3*x - 10 = 0");
		System.out.println("\n2*(y^2) + 4 = 9*y");
		probFromTemplate("2*(y^2) + 4 = 9*y");
		System.out.println("\n2*(x^2) = 8*(x + 3)");
		probFromTemplate("2*(x^2) = 8*(x + 3)");
		System.out.println("\nx^2 = 9*x - 20");
		probFromTemplate("x^2 = 9*x - 20");
	}
	
	public void recognitionTest2() throws RecognitionException{
		System.out.println("x^2 = 15 + 2*x");
		probFromTemplate("x^2 = 15 + 2*x");
		System.out.println("\nx^2 - 10*x + 35 = 7*x - 35");
		probFromTemplate("x^2 - 10*x + 35 = 7*x - 35");
		System.out.println("\n2*x^2 + 5 + 20*x = 20 - 8*x^2 + x");
		probFromTemplate("2*x^2 + 5 + 20*x = 20 - 8*x^2 + x");
		System.out.println("\n3 = 16*x - 20*x^2");
		probFromTemplate("3 = 16*x - 20*x^2");
		System.out.println("\n8*x = 0.5*x^2 + 31.5");
		probFromTemplate("8*x = 0.5*x^2 + 31.5");
		System.out.println("\nx^2 + 7*x + x^2 - 10 = 5");
		probFromTemplate("x^2 + 7*x + x^2 - 10 = 5");
		System.out.println("\nx^2 - 7.5*x + 25 = -1*x^2 - 7.5*x");
		probFromTemplate("x^2 - 7.5*x + 25 = -x^2 - 7.5*x");
	}
	
	public void inputTest() throws IOException, RecognitionException{
		 InputStreamReader iStream = new InputStreamReader(System.in) ;
		 BufferedReader bRead = new BufferedReader(iStream) ;
		 System.out.println("\nEnter template:");
		 String type = bRead.readLine();
		 Problem prob = probFromTemplate(type);
		 System.out.println("Enter solution:");
		 String answer = bRead.readLine();
		 DecimalFormat df = new DecimalFormat("#.###");
		 boolean correct = false;
		 if(prob.id == 0){
			 if(answer.equals(df.format(prob.getNumSolution()))){
				 correct = true;
			 }
		 }else if(prob.id == 1){
			 if(prob.equLineId == 0){
				 String a = answer.replaceAll(" ", "");
				 String s = prob.getSlopeForm();
				 String p =s.replaceAll(" ", "");
				 if(p.equals(a)){
					 correct = true;
				 }
			 }else if(prob.equLineId == 1){
				 String a = (answer.replaceAll(" ", ""));
				 String s = (prob.getGeneralForm().replaceAll(" ", ""));
				 s = s.trim();
				 System.out.println("a: "+a);
				 System.out.println("p: "+s);
				 if(s.equals(a)){
					 correct = true;
				 }
			 }else if(prob.equLineId == 2){
				 if(answer.equals(df.format(prob.getYInt()))){
					 correct = true;
				 }
			 }else if(prob.equLineId == 3){
				 if(answer.equals(df.format(prob.getSlope()))){
					 correct = true;
				 }
			 }
		 }else if(prob.id == 2){
			 //Problem is a quadratic equation
			 double[] roots = prob.getQuadSolution();
			 int qNum = 0;
			 for(int i=0; i<roots.length; i++){
				 if((i==roots.length-1) && 
						 (answer.contains(", "+df.format(roots[i])) || answer.contains(","+df.format(roots[i])))){
					 qNum++;
				 }else if(answer.contains(df.format(roots[i])+",")
						 || answer.contains(df.format(roots[i])+", ")){
					 qNum++;
				 }
			 }
			 if(qNum == roots.length){
				 correct = true;
			 }
		 }
		 
		 if(correct){
			 System.out.println("Correct!");
		 }else{
			 System.out.println("Incorrect answer");
		 }
	}
	
	public Problem runTest(Problem prob) throws RecognitionException{
		CharStream charStream = new ANTLRStringStream(prob.getTemplate());
		BasicAlgebraEquLexer lexer = new BasicAlgebraEquLexer(charStream);
		TokenStream tokenStream = new CommonTokenStream(lexer);
		BasicAlgebraEquParser parser = new BasicAlgebraEquParser(tokenStream);
		evaluator_return eval;
		eval = parser.evaluator();
		CommonTreeNodeStream nodeStream = new CommonTreeNodeStream(eval.tree);
		AlgebraGrammarEvaluator walker = new AlgebraGrammarEvaluator(nodeStream);
		//double r = walker.evaluator();
		PolynomialEquation p = walker.evaluator();
		if(p == null){
			System.out.println("p is null");
			return null;
		}
		prob.setProblem(p.toString());
		//System.out.println("Max degree: " + p.maxDegree());
		
		//System.out.println(p);
		if(p.maxDegree() == 1){
			 if(p.variables.size()==1){
				 prob.setSolution(p.singleVariableSolution());
			 }else if(p.variables.contains('x') && p.variables.contains('y')){
				 prob.setSolution(p.printSlopeIntercept(), p.printGeneralForm(), p.yIntercept(), p.slope());
				 //System.out.println("y-intercept: "+p.yIntercept());
				 //System.out.println("slope: "+p.slope());
				 //p.generalForm();
			 }
		}else if(p.maxDegree() == 2){
			prob.setSolution(p.quadratic());
		}else{
			System.out.println("Problem not valid");
			return null;
		}
		System.out.println(prob);
		//System.out.println("Id: "+prob.id);
		
		return prob;
	}
	
	public Problem probFromTemplate(String temp) throws RecognitionException{
		return runTest(new Problem(temp));
	}
	
}